package bb.lanxing.util;

import static com.blankj.utilcode.util.ColorUtils.getColor;

import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;

import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.Overlay;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.map.PolylineOptions;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.model.LatLngBounds;
import com.github.mikephil.charting.utils.Utils;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

import bb.lanxing.R;
import bb.lanxing.common.config.Constants;
import bb.lanxing.common.config.UnitConstants;
import bb.lanxing.model.data.Notepoint;
import bb.lanxing.model.database.RouteBook;
import bb.lanxing.model.database.RouteBookPoint;
import bb.lanxing.model.database.Waypoint;
import bb.lanxing.network.GoogleClient;
import bb.lanxing.network.MyHttpClient;
import bb.lanxing.util.ui.DrawableUtils;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;

public class MapUtil {
    final static private String TAG = "MapUtil";

    public interface RequestDataListener<T> {
        void onResult(T result);
    }

    public static List<Overlay> drawStaticWorkout(BaiduMap baiduMap, List<LatLng> workoutPoints) {
        return drawWorkout(baiduMap, workoutPoints, 10, Constants.MAP_DEFAULT_LINE_COLOR, true, true);
    }

    public static List<Overlay> drawSportWorkout(BaiduMap baiduMap, List<LatLng> workoutPoints) {
        return drawWorkout(baiduMap, workoutPoints, 10, Constants.MAP_DEFAULT_LINE_COLOR, true, false, false);
    }

    public static List<Overlay> drawWorkout(BaiduMap baiduMap, List<LatLng> workoutPoints, int width, int color, boolean drawStartPoint, boolean drawEndPoint) {
        return drawWorkout(baiduMap, workoutPoints, width, color, drawStartPoint, drawEndPoint, true);
    }

    public static List<Overlay> drawWorkout(BaiduMap baiduMap, List<LatLng> workoutPoints, int width, int color, boolean drawStartPoint, boolean drawEndPoint, boolean bound) {
        if (baiduMap == null || workoutPoints == null || workoutPoints.isEmpty()) {
            return null;
        }
        ArrayList arrayList = new ArrayList();
        arrayList.add(drawLine(baiduMap, workoutPoints, width, color, bound));
        if (drawStartPoint) {
            arrayList.add(addStartMark(baiduMap, workoutPoints.get(0)));
        }
        if (drawEndPoint) {
            arrayList.add(addStopMark(baiduMap, workoutPoints.get(workoutPoints.size() - 1)));
        }
        return arrayList;
    }

    public static List<Overlay> drawSportLushu(BaiduMap baiduMap, RouteBook routeBook, List<LatLng> lushuBaiduPoints, List<LatLng> wayBaiduPoints, List<LatLng> noteBaiduPoints) {
        return drawLushu(baiduMap, routeBook, lushuBaiduPoints, wayBaiduPoints, noteBaiduPoints, 11, Constants.LUSHU_LINE_COLOR, false);
    }

    public static List<Overlay> drawSportLushu(BaiduMap baiduMap, RouteBook routeBook, boolean prepare) {
        List<RouteBookPoint> lushuPoints = RouteBookPoint.getByLushuId(routeBook.getId());
        List<Waypoint> wayPoints = Waypoint.getByLushuId(routeBook.getId());
        List<Notepoint> notepointList = routeBook.getNotepointList();
        ArrayList<LatLng> lushuBaiduPoints = new ArrayList<>(lushuPoints.size());
        ArrayList<LatLng> wayBaiduPoints = new ArrayList<>(wayPoints.size());
        ArrayList<LatLng> noteBaiduPoints = new ArrayList<>(notepointList.size());
        for (RouteBookPoint lushuPoint : lushuPoints) {
            lushuBaiduPoints.add(BiCiCoorConverter.earth2Baidu(lushuPoint.getLatLng()));
        }
        for (Waypoint waypoint : wayPoints) {
            wayBaiduPoints.add(BiCiCoorConverter.earth2Baidu(waypoint.getLatLng()));
        }
        for (Notepoint notepoint : notepointList) {
            noteBaiduPoints.add(BiCiCoorConverter.earth2Baidu(notepoint.getLatLng()));
        }
        int color = prepare ? getColor(R.color.holo_red_light) : getColor(R.color.blue1);
        return drawSportLushu(baiduMap, routeBook, lushuBaiduPoints, wayBaiduPoints, noteBaiduPoints, color, true);
    }

    public static List<Overlay> drawSportLushu(BaiduMap baiduMap, RouteBook routeBook, List<LatLng> lushuBaiduPoints, List<LatLng> wayBaiduPoints, List<LatLng> noteBaiduPoints, int color, boolean bound) {
        return drawLushu(baiduMap, routeBook, lushuBaiduPoints, wayBaiduPoints, noteBaiduPoints, 11, color, bound);
    }

    public static List<Overlay> drawLushu(BaiduMap baiduMap, RouteBook routeBook, List<LatLng> lushuBaiduPoints, List<LatLng> wayBaiduPoints, List<LatLng> noteBaiduPoints, int width, int color, boolean bound) {
        if (baiduMap == null || routeBook == null || lushuBaiduPoints == null || lushuBaiduPoints.isEmpty()) {
            return null;
        }
        List<Waypoint> wayPoints = routeBook.getWayPoints();
        List<Notepoint> notepointList = routeBook.getNotepointList();
        ArrayList<Overlay> arrayList = new ArrayList<>();
        arrayList.add(drawLine(baiduMap, lushuBaiduPoints, width, color, bound));
        arrayList.add(addStartMark(baiduMap, lushuBaiduPoints.get(0)));
        arrayList.add(addStopMark(baiduMap, lushuBaiduPoints.get(lushuBaiduPoints.size() - 1)));
        if (wayPoints != null && !wayPoints.isEmpty()) {
            arrayList.addAll(drawWaypoints(baiduMap, wayPoints, wayBaiduPoints));
        }
        if (notepointList != null && !notepointList.isEmpty()) {
            arrayList.addAll(drawNotepoints(baiduMap, notepointList, noteBaiduPoints));
        }
        return arrayList;
    }

    public static Overlay drawLine(BaiduMap baiduMap, List<LatLng> latLngs) {
        return drawLine(baiduMap, latLngs, Constants.MAP_DEFAULT_LINE_WIDTH, Constants.MAP_DEFAULT_LINE_COLOR, true);
    }

    public static Overlay drawLine(final BaiduMap baiduMap, final List<LatLng> latLngs, int width, int color, boolean bound) {
        return drawLine(baiduMap, latLngs, width, color, 0, bound, false);
    }

    public static Overlay drawLine(final BaiduMap baiduMap, final List<LatLng> latLngs, int width, int color, int zindex, boolean bound, boolean isDottedLine) {
        Overlay overlay = null;
        if (baiduMap != null && latLngs != null && latLngs.size() >= 2) {
            try {
                PolylineOptions points = new PolylineOptions().points(latLngs);
                if (isDottedLine) {
                    width = (int) (width / 1.5d);
                }
                overlay = baiduMap.addOverlay(points.width(width).zIndex(zindex).dottedLine(isDottedLine).color(color));
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (bound) {
                displayWithBound(baiduMap, latLngs);
                baiduMap.setOnMapLoadedCallback(new BaiduMap.OnMapLoadedCallback() {
                    @Override
                    public void onMapLoaded() {
                        Log.v(TAG, "onMapLoaded");
                        MapUtil.displayWithBound(baiduMap, latLngs);
                    }
                });
            }
        }
        return overlay;
    }

    public static void displayWithBound(BaiduMap baiduMap, List<LatLng> latLngs) {
        if (baiduMap == null || latLngs == null) {
            return;
        }
        LatLngBounds.Builder builder = new LatLngBounds.Builder();
        for (LatLng latLng : latLngs) {
            builder.include(latLng);
        }
        LatLngBounds build = builder.build();
        try {
            baiduMap.setMapStatus(MapStatusUpdateFactory.newLatLngBounds(build));
            baiduMap.setMapStatus(MapStatusUpdateFactory.newLatLng(build.getCenter()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static List<Marker> drawWaypoints(final BaiduMap baiduMap, final List<Waypoint> waypoints, List<LatLng> wayBaiduPoints) {
        Marker marker;
        if (baiduMap == null || waypoints == null || waypoints.size() != wayBaiduPoints.size()) {
            return null;
        }
        ArrayList<Marker> arrayList = new ArrayList<>();
        ArrayList<Waypoint> arrayList2 = new ArrayList<>();
        for (int i = 0; i < waypoints.size(); i++) {
            Waypoint waypoint = waypoints.get(i);
            LatLng latLng = wayBaiduPoints.get(i);
            if (waypoint.getType() == Waypoint.TYPE_CHECK) {
                marker = addMark(baiduMap, latLng, R.drawable.ic_lushu_map_checkpoint);
                Bundle bundle = new Bundle();
                bundle.putParcelable("infoPoint", waypoint);
                marker.setExtraInfo(bundle);
                arrayList2.add(waypoint);
            } else {
                marker = null;
            }
            arrayList.add(marker);
        }
        return arrayList;
    }

    public static List<Marker> drawNotepoints(BaiduMap baiduMap, List<Notepoint> notepointList, List<LatLng> noteBaiduPoints) {
        if (baiduMap == null || notepointList == null || notepointList.size() != noteBaiduPoints.size()) {
            return null;
        }
        ArrayList<Marker> arrayList = new ArrayList<>();
        for (int i = 0; i < notepointList.size(); i++) {
            Marker addMark = addMark(baiduMap, noteBaiduPoints.get(i), R.drawable.ic_lushu_edit_map_waypoint);
            Bundle bundle = new Bundle();
            bundle.putParcelable("infoPoint", notepointList.get(i));
            addMark.setExtraInfo(bundle);
            arrayList.add(addMark);
        }
        return arrayList;
    }

    public static Marker addStartMark(BaiduMap baiduMap, LatLng latLng) {
        return addMark(baiduMap, latLng, R.drawable.ic_location_start, 0.5f, 0.5f);
    }

    public static Marker addStopMark(BaiduMap baiduMap, LatLng latLng) {
        return addMark(baiduMap, latLng, R.drawable.ic_location_stop, 0.5f, 0.5f);
    }

    public static Marker addMark(BaiduMap baiduMap, LatLng latLng, int res) {
        if (baiduMap == null) {
            return null;
        }
        return (Marker) addOverlay(baiduMap, new MarkerOptions().position(latLng).icon(BitmapDescriptorFactory.fromResource(res)));
    }

    public static Marker addMark(BaiduMap baiduMap, LatLng latLng, int res, float anchorX, float anchorY) {
        return addMark(baiduMap, latLng, res, anchorX, anchorY, 0);
    }

    public static Marker addMark(BaiduMap baiduMap, LatLng latLng, int res, float anchorX, float anchorY, int zindex) {
        if (baiduMap == null) {
            return null;
        }
        return (Marker) addOverlay(baiduMap, new MarkerOptions().anchor(anchorX, anchorY).position(latLng).zIndex(zindex).icon(BitmapDescriptorFactory.fromResource(res)));
    }

    public static Overlay addOverlay(BaiduMap baiduMap, OverlayOptions options) {
        if (baiduMap == null) {
            return null;
        }
        try {
            return baiduMap.addOverlay(options);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void setMapStatus(BaiduMap baiduMap, MapStatusUpdate mapStatusUpdate) {
        if (baiduMap == null) {
            return;
        }
        try {
            baiduMap.animateMapStatus(mapStatusUpdate);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void requestAltitude(final double latitude, final double longitude, final RequestDataListener<Double> listener) {
        MyHttpClient.requestElevation(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                MapUtil.requestAltitudeFromXZ(latitude, longitude, listener);
            }

            @Override
            public void onResponse(Call call, Response response) {
                try {
                    String string = response.body().string();
                    Log.d(TAG, "requestAltitude : " + string);
                    JSONObject jSONObject = new JSONObject(string);
                    if ("OK".equalsIgnoreCase(jSONObject.getString("status"))) {
                        double handlerAltitudeResult = MapUtil.handlerAltitudeResult(jSONObject);
                        RequestDataListener requestDataListener = listener;
                        if (requestDataListener != null) {
                            requestDataListener.onResult(handlerAltitudeResult);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    MapUtil.requestAltitudeFromXZ(latitude, longitude, listener);
                }
            }
        }, latitude, longitude);
    }

    public static void requestAltitudeFromXZ(double latitude, double longitude, final RequestDataListener<Double> listener) {
        LatLng curLatLng = new LatLng(latitude, longitude);
        GoogleClient.requestAltitude(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {
                    String string = response.body().string();
                    Log.d(TAG, "requestAltitude : " + string);
                    JSONObject jSONObject = new JSONObject(string);
                    if ("OK".equalsIgnoreCase(jSONObject.getString("status"))) {
                        double handlerAltitudeResult = MapUtil.handlerAltitudeResult(jSONObject);
                        RequestDataListener requestDataListener = listener;
                        if (requestDataListener != null) {
                            requestDataListener.onResult(Double.valueOf(handlerAltitudeResult));
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, curLatLng, false);
    }

    public static double handlerAltitudeResult(JSONObject jsonObject) {
        try {
            return jsonObject.has("results") ? jsonObject.getJSONArray("results").getJSONObject(0).getDouble("elevation") : Utils.DOUBLE_EPSILON;
        } catch (JSONException e) {
            e.printStackTrace();
            return Utils.DOUBLE_EPSILON;
        }
    }

    public static Drawable convertView(View view) {
        return DrawableUtils.convertDrawable(view);
    }

    public static String formatDistance(double distance) {
        String str;
        DecimalFormat decimalFormat = new DecimalFormat();
        if (distance < 1000.0d) {
            decimalFormat.applyPattern("0");
            str = "m";
        } else {
            decimalFormat.applyPattern("0.00");
            distance /= 1000.0d;
            str = UnitConstants.UNIT_SIZE_KM;
        }
        return decimalFormat.format(distance) + str;
    }

    public static String formatAltitude(double distance) {
        DecimalFormat decimalFormat = new DecimalFormat();
        decimalFormat.applyPattern("0");
        return decimalFormat.format(distance) + "m";
    }
}